package dev.mcdd.user.service;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import dev.mcdd.common.constant.RoleType;
import dev.mcdd.security.helper.PasswordEncoderHelper;
import dev.mcdd.auth.domain.request.RegisterVo;
import dev.mcdd.user.entity.Role;
import dev.mcdd.user.entity.User;
import dev.mcdd.user.exception.EmailAlreadyExistException;
import dev.mcdd.user.exception.UserNotfoundException;
import dev.mcdd.user.mapper.UserMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

/**
 * UserServiceImpl
 *
 * @author: mcdd1024
 * @date 2025/1/16 05:29
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {


    private final RoleService roleService;

    @Override
    public Optional<User> loadUserByText(String text) {
        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<User>()
            .eq(User::getUsername, text)
            .or()
            .eq(User::getEmail, text);
        User user = this.getOneOpt(userLambdaQueryWrapper)
            .orElseThrow(() -> new UserNotfoundException(String.format("User with email %s not found", text)));
        Long userId = user.getId();
        Role role = roleService.loadRoleByUserId(userId);
        user.setRole(role);
        return Optional.of(user);
    }

    @Override
    @Transactional
    public User saveUser(RegisterVo vo) {
        String email = vo.email();
        verifyEmail(email);
        String username = vo.username();
        String password = vo.password();
        User user = new User();
        user.setUsername(username);
        user.setEmail(email);
        user.setPassword(PasswordEncoderHelper.encryptPassword(password));
        boolean save = this.save(user);
        if (!save) {
            throw new RuntimeException("save failed");
        }
        return roleService.authorizationUserRole(user, RoleType.USER);
    }

    private Boolean isEmailExists(String email) {
        return this.exists(new LambdaQueryWrapper<User>().eq(User::getEmail, email));
    }

    private void verifyEmail(String email) {
        if (this.isEmailExists(email)) {
            throw new EmailAlreadyExistException(String.format("Email %s already exists", email));
        }
    }

}